package com.bjfu.college.controller;


import com.bjfu.college.common.ErrorCode;
import com.bjfu.college.common.ResultUtils;
import com.bjfu.college.dto.FilterCondition;
import com.bjfu.college.dto.SchemeDisplay;
import com.bjfu.college.pojo.ColumnTitleMap;
import com.bjfu.college.pojo.StudentInfo;
import com.bjfu.college.pojo.StudentInfoIntentionScheme;
import com.bjfu.college.pojo.UniversityIntentionRecord;
import com.bjfu.college.service.*;
import com.bjfu.college.utils.ExcelUtils;
import com.bjfu.college.utils.ListUtils;
import com.bjfu.college.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 志愿填报 控制层
 *
 * @author xgy
 * @since 2023-07-8
 */
@Slf4j
@RestController
@RequestMapping("/college")
public class CollegeApplicationController {


    @Autowired
    UniversityIntentionRecordService universityIntentionRecordService;

    @Autowired
    UniversityIntentionSchemeService universityIntentionSchemeService;

    @Autowired
    IntentionSchemeIntentionRecordService intentionSchemeIntentionRecordService;

    @Autowired
    StudentInfoIntentionSchemeService studentInfoIntentionSchemeService;

    @Autowired
    StudentInfoService studentInfoService;

    /**
     * 志愿记录批量导入
     * @param file xxx.xlsx文件
     * @return
     * @throws Exception
     */
    @PostMapping("/excelInsert")
    public Object excelRegister(MultipartFile file) throws Exception {
        if (file==null || file.isEmpty()){
            return ResultUtils.error(ErrorCode.PARAMS_ERROR,"文件为空，请选择文件！");
        }

        String filename = file.getOriginalFilename();
        assert filename != null;
        if (!filename.endsWith(".xlsx")){
            return ResultUtils.error(ErrorCode.PARAMS_ERROR,"文件格式错误！");
        }

        // 获取Excel中的数据,一个Map代表一行的数据,多个Map组成整张sheet
        List<Map<String,String>> list = ExcelUtils.excelToShopIdList(file.getInputStream());
        if(list.isEmpty())
            return ResultUtils.error(ErrorCode.PARAMS_ERROR,"文件数据为空，请录入数据！");

        System.out.println("当前excel行数:"+list.size());
        System.out.println("当前excel列数:"+list.get(0).keySet().size());

        //根据选科组合与选科要求对应数据，建立学科与学科要求的map
        Map<String,List<String>> subjectMap = new HashMap<>();
        if(list.get(0).get("col0").equals("选科组合") && list.get(0).get("col1").equals("选科要求")) {
            for (int i = 1; i < list.size(); i++) {
                String subject = list.get(i).get("col0");
                String subjectRequirement = list.get(i).get("col1");
                List<String> subjectRequirementList = subjectMap.getOrDefault(subject, new ArrayList<>());
                subjectRequirementList.add(subjectRequirement);
                subjectMap.put(subject, subjectRequirementList);
            }
        }
       return ResultUtils.success(subjectMap);
    }

    /**
     * @Description: 志愿方案Excel文件导出
     * @Author: Pzf
     * @Date:   2023/7/17 8:30
     * @Param:  [schemeId, response]
     * @Return: java.lang.Object
     */
    @GetMapping("/exportExcel")
    public Object exportExcel(int schemeId,HttpServletResponse response) throws IOException {
        // 通过方案id获取Map<方案属性名，方案属性值>的列表
        List<Map<String, Object>> recordsResultListMap = universityIntentionRecordService.getRecordsResultListMap(schemeId);
        if (recordsResultListMap.size() < 96){
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR,"该方案的记录数少于96条，无法导出，请新增记录再进行导出",ErrorCode.SYSTEM_ERROR.getDescription());
        }
        // 获取mysql中的字段名称列表
        ArrayList<String> titleKeyList= new ColumnTitleMap("recordsInfo").getTitleKeyList();
        // mysql字段列表与Excel表头对应关系Map
        Map<String, String> titleMap = new ColumnTitleMap("recordsInfo").getColumnTitleMap();

        ExcelUtils.exportDataExcel(response,titleKeyList,titleMap,recordsResultListMap);

        return ResultUtils.success("导出Excel文件成功");

    }

    /**
     * @Description: 获取所有学生的信息
     * @Author: Pzf
     * @Date:   2023/7/17 8:36
     * @Param:  []
     * @Return: java.lang.Object
     */
    @GetMapping("/allStudentInfo")
    public Object getAllStudentInfo(){
        List<StudentInfo> studentInfos = studentInfoService.list();
        if (ListUtils.listValidityJudge(studentInfos)){
            return ResultUtils.success(studentInfos);
        }
        return ResultUtils.error(ErrorCode.NULL_ERROR,"学生信息为空");
    }

    /**
     * @Description: 获取学生的详细信息
     * @Author: Pzf
     * @Date:   2023/7/21 0:35
     * @Param:  [studentId, request]
     * @Return: java.lang.Object
     */
    @GetMapping("/studentInfo")
    public Object getOneStudentInfo(int studentId, HttpServletRequest request){
        StudentInfo studentInfo = studentInfoService.getById(studentId);
        // 会话设置student属性，方便获取学生信息
        request.getSession().setAttribute("student",studentInfo);
        System.out.println("当前session值:" + request.getSession().getAttribute("student"));
        // 获取学生的方案筛选条件
        List<StudentInfoIntentionScheme> conditions = studentInfoIntentionSchemeService.getConditions(studentId);

        List<RiskInfo> riskRecordsLists = new ArrayList<>();
        for (int i = 0; i < conditions.size(); i++) {
            RiskInfo riskInfo = new RiskInfo();
            riskInfo.setSchemeId(conditions.get(i).getSchemeId());
            List<Integer> riskBySchemeId = intentionSchemeIntentionRecordService.queryRiskBySchemeId(riskInfo.getSchemeId());
            riskInfo.setRiskRecordsCount(riskBySchemeId);
            riskRecordsLists.add(riskInfo);
        }

        // 学生信息和方案筛选条件放入vo传递给前端
        StudentInfoVO studentInfoVo = new StudentInfoVO(studentInfo, conditions,riskRecordsLists);
        return ResultUtils.success(studentInfoVo);
    }

    /**
     * @Description: “保存” 按钮的 api
     * @Author: Pzf
     * @Date:   2023/7/16 14:13
     * @Param:  [filterCondition, request]
     * @Return: java.lang.Object
     */
    @PostMapping("/saveAndOptimize")
    @Transactional
    public Object saveAndOptimize(@RequestBody FilterCondition filterCondition ,HttpServletRequest request) throws Exception{
        System.out.println("当前session值:" + request.getSession().getAttribute("student"));
        System.out.println("FilterCondition:"+filterCondition);
        // 返回给前端的数组，表述冲，稳，保的记录数各有几条
        RiskInfo riskInfo;
        // 获取会话属性中的学生信息
        StudentInfo student = (StudentInfo) request.getSession().getAttribute("student");
        if(student==null)
            return ResultUtils.error(ErrorCode.NOT_LOGIN,"请先选择学生对象");
        // 根据筛选条件获取志愿记录列表
        List<UniversityIntentionRecord> universityIntentionRecordsByCondition = universityIntentionRecordService.getUniversityIntentionRecordsByCondition(filterCondition, student.getProvince(), student.getScore(),student.getSelectiveCombination());
        // 先判断符合条件的记录数是否在100到300之间
        if (universityIntentionRecordsByCondition != null && universityIntentionRecordsByCondition.size() < 100){
            return ResultUtils.error(ErrorCode.PARAMS_ERROR,"志愿记录数不足，请重新筛选！",ErrorCode.PARAMS_ERROR.getDescription());
        } else if ( universityIntentionRecordsByCondition != null && universityIntentionRecordsByCondition.size() > 300){
            return ResultUtils.error(ErrorCode.PARAMS_ERROR,"志愿记录数过多，请重新筛选！",ErrorCode.PARAMS_ERROR.getDescription());
        }

        // 新生成方案
        int newSchemeId = universityIntentionSchemeService.insertScheme(student.getId());
        if (newSchemeId == 0) return ResultUtils.error(ErrorCode.SYSTEM_ERROR,"该学生的方案数已满，请删除现有方案再保存新方案",ErrorCode.SUCCESS.getDescription());
        // 中间表插入
        riskInfo = intentionSchemeIntentionRecordService.addSchemeRecordRelation(universityIntentionRecordsByCondition, newSchemeId, student.getScore(), filterCondition.getScoreBias());
        // 风险信息判断
        if (riskInfo == null || riskInfo.getRiskRecordsCount().size() == 0) throw new RuntimeException("中间表插入有误");
        // 筛选条件的保存
        studentInfoIntentionSchemeService.saveCondition(student.getId(),newSchemeId,filterCondition,false);
        // vo的构建
        StudentInfoIntentionScheme condition = studentInfoIntentionSchemeService.getCondition(newSchemeId, student.getId());
        SchemeSaveVO schemeSaveVo = new SchemeSaveVO(riskInfo, condition);
        return ResultUtils.success(schemeSaveVo);
    }

    /**
     * @Description: 调整位次以及优化 的 api(动态参数)
     * @Author: Pzf
     * @Date:   2023/7/16 14:19
     * @Param:  [schemeDisplay]
     * @Return: java.lang.Object
     */
    @PostMapping("/schemeOptimize")
    public Object schemeOptimize(@RequestBody SchemeDisplay schemeDisplay){
        // 根据数据对象中是否调整位次的属性，判断是否需要调整位次
        if (schemeDisplay.getIsOrder() != null &&  schemeDisplay.getIsOrder() == true){
            // 如果是调整位次的请求,则先对中间表中rank字段进行更新
            intentionSchemeIntentionRecordService.updateRecordsRankById(schemeDisplay.getSchemeId(), schemeDisplay.getRecordId(), schemeDisplay.getRecordNewRank());
        }
        // 获取页对象
        IPageVO iPageVO = universityIntentionRecordService.getUniversityIntentionRecordsById(schemeDisplay.getPageNum(), schemeDisplay.getPageSize(), schemeDisplay.getSchemeId());
        return ResultUtils.success(iPageVO);
    }

    /**
     * @Description: 根据前端传来的方案id对方案进行删除
     * @Author: Pzf
     * @Date:   2023/7/16 18:29
     * @Param:  [schemeId]
     * @Return: java.lang.Object
     */
    @GetMapping("/schemeDelete")
    @Transactional
    public Object schemeDelete(int schemeId){
        intentionSchemeIntentionRecordService.deleteSchemeRecordRelation(schemeId);
        studentInfoIntentionSchemeService.deleteCondition(schemeId);
        universityIntentionSchemeService.deleteScheme(schemeId);
        // 返回删除后的所有方案
        return ResultUtils.success(universityIntentionSchemeService.list());
    }

    /**
     * @Description: 根据方案id与记录id进行某方案中的记录逻辑删除
     * @Author: Pzf
     * @Date:   2023/7/17 8:28
     * @Param:  [schemeDisplay]
     * @Return: java.lang.Object
     */
    @PostMapping("/recordDelete")
    public Object recordDelete(@RequestBody SchemeDisplay schemeDisplay){
        intentionSchemeIntentionRecordService.logicDelete(schemeDisplay.getSchemeId(),schemeDisplay.getRecordId());
        return ResultUtils.success("当前记录删除成功");
    }


    /**
     * @Description: 方案的新增记录按钮，返回该方案被逻辑删除的记录
     * @Author: Pzf
     * @Date:   2023/7/16 18:32
     * @Param:  [schemeId]
     * @Return: java.lang.Object
     */
    @PostMapping("/addNewRecord")
    public Object addNewRecord(@RequestBody SchemeDisplay schemeDisplay){
        IPageVO iPageVO = universityIntentionRecordService.getUniversityIntentionRecordsIsDeleted(schemeDisplay.getPageNum(),schemeDisplay.getPageSize(),schemeDisplay.getSchemeId());
        return ResultUtils.success(iPageVO);
    }

    /**
     * @Description: 方案新增记录勾选后
     * @Author: Pzf
     * @Date:   2023/7/16 21:07
     * @Param:  [recordIds]
     * @Return: java.lang.Object
     */
    @PostMapping("/newRecordSave")
    public Object newRecordSave(@RequestBody SchemeDisplay schemeDisplay){
        // 逻辑删除恢复
        intentionSchemeIntentionRecordService.recoverLogicDeleted(schemeDisplay.getSchemeId(),schemeDisplay.getRecordIds());
        List<RecordDetail> recordsBySchemeId = universityIntentionRecordService.getUniversityIntentionRecordsById(schemeDisplay.getPageNum(),schemeDisplay.getPageSize(),schemeDisplay.getSchemeId()).getList();
        return ResultUtils.success(recordsBySchemeId);
    }
}
